<?php

namespace Modules\System\Services\Sys;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Modules\System\Services\Mds\MDSArray;

class Database
{

    /**
     * 万能添加
     * @param direction
     */
    static public function insert($i,$user = []){

        self::verification($i,$user);

        $re_id = DB::transaction(function() use ($i,$user){

            if(isset($i['dbData'])){
                $i['dbData'] = MDSArray::jsonToArray($i['dbData']);
            }else{
                $i['dbData'] = [];
            }

            $model = $i['model'];

            //针对不同的模型做不同的处理
            if(method_exists($model,"mdsInsert")){
                $i = $model::mdsInsert($i,$user);
            }

            if(isset($i['over'])){
                return $i['return'];
            }

            if(!isset($i['dbData']['created_at'])){
                $i['dbData']['created_at'] = date("Y-m-d H:i:s");
            }

            $re_id = $model::insertGetId($i['dbData']);

            return $re_id;

        });

        return $re_id;

    }

    /**
     * 万能删除
     * @param direction
     */
    static public function delete($i,$user = []){

        self::verification($i,$user);

        if(empty($user)){
            mdsResponse(400,"必须传正确的token");
        }

        //同步操作都需要事务
        $re = DB::transaction(function() use ($i,$user){
            $model = $i['model'];
            //针对不同的模型做不同的处理
            if(method_exists($model,"mdsDelete")){
                $i = $model::mdsDelete($i,$user);
            }
            if(!isset($i['where']) || empty($i['where'])){
                mdsResponse(400,"请传入条件");
            }
            $re = $model::where(function($query) use ($i){
                self::splicingWhere($i,$query);
            })->delete();
            return $re;

        });

        return $re;

    }

    /**
     * 万能修改
     * @param direction
     */
    static public function update($i,$user = []){

        self::verification($i,$user);

        if(empty($user)){
            mdsResponse(400,"必须传正确的token");
        }

        $re = DB::transaction(function() use ($i,$user){

            $i['dbData'] = MDSArray::jsonToArray($i['dbData']??[]);

            $model = $i['model'];
            //针对不同的模型做不同的处理
            if(method_exists($model,"mdsUpdate")){
                $i = $model::mdsUpdate($i,$user);
            }

            if(isset($i['over'])){
                return $i['return'];
            }

            if(!isset($i['where']) || empty($i['where'])){
                mdsResponse(400,"请传入条件");
            }
            if(!isset($i['dbData']) || empty($i['dbData'])){
                mdsResponse(400,"请传入修改数据");
            }
            if(!isset($i['dbData']['updated_at'])){
                $i['dbData']['updated_at'] = date("Y-m-d H:i:s");
            }
            $re = $model::where(function($query) use ($i){
                self::splicingWhere($i,$query);
            })->update($i['dbData']);

            $thisData = $model::where(function($query) use ($i){
                self::splicingWhere($i,$query);
            })->first();

            return ["re" => $re,"newData" => $thisData];

        });

        return $re;

    }

    /**
     * 万能搜索
     * @param direction
     */
    static public function search($i,$user = []){

        self::verification($i,$user);

        $i['type'] = isset($i['type']) ? $i['type'] : "list";      //默认二维数组

        $model = $i['model'];

        //针对不同的模型做不同的处理
        if(method_exists($model,"mdsSearchBegin")){
            $i = $model::mdsSearchBegin($i,$user);
        }

        if(isset($i['over'])){
            return $i['return'];
        }

        $pazeSize = isset($i['pazeSize']) ? $i['pazeSize'] : 500;       //默认500条数据
        if(!isset($i['page'])){
            $i['page'] = 1;
        }

        $with = MDSArray::strToArray($i['with']??[],",");

        $orderBy = true;
        if(empty($i['orderBy'])){
            $orderBy = false;
        }

        //DB::connection()->enableQueryLog(); // 开启查询日志
        $list = $model::with($with)                                    //$with是一个一维数组
            ->offset(($i['page'] - 1) * $pazeSize)
            ->where(function($query) use ($i){
                if(isset($i['where']) && $i['where'] != ''){
                    self::splicingWhere($i,$query);
                }
            })->when($orderBy,function($query,$sortBy) use ($i,$model){
                $orderBy = MDSArray::jsonToArray($i['orderBy']);
                if(empty($orderBy)){
                    mdsResponse(400,"排序数据错误");
                }
                foreach($orderBy as $k => $v){
                    $query->orderBy($v['field'],$v['sort']);
                }
            },function($query) use ($i,$model){
                return $query->orderBy($model::getPrimaryKey(),"desc");
            })
            ->limit($pazeSize)
            ->get();
        //d(DB::getQueryLog());

        //针对不同的模型做不同的处理
        if(method_exists($model,"mdsSearchEnd")){
            $list = $model::mdsSearchEnd($list,$i,$user);
        }

        if($i['type'] == "one"){
            return $list[0]??[];
        }else{
            return $list;
        }

    }

    /**
     * 前边验证
     */
    static public function verification($i,$user){
        $validator = Validator::make(
            $i,
            [
                'model' => "required",
            ],
            [
                'model.required' => 'model不能为空',
            ]
        );

        if(!empty($validator->errors()->first())){
            mdsResponse(400,$validator->errors()->first());
        }

        if(empty($user)){
            mdsResponse(400,"必须传正确的token");
        }
    }

    /**
     * 整理连接参数
     */
    static public function transformation($i){

        $i = self::sort($i);
        //d($i);
        //转换操作
        foreach($i as $ki => $vi){

            //--where----------------------------------------
            //在一堆数据中in,数据用逗号隔开
            if(strpos($ki,'whereIn_') !== false){
                $one['field'] = str_replace("whereIn_","",$ki);
                $one['condition'] = "in";
                $one['val'] = MDSArray::strToArray($vi,",");
                $i['where'][] = $one;
            }

            //不在某堆数据中
            if(strpos($ki,'whereNotIn_') !== false){
                $one['field'] = str_replace("whereNotIn_","",$ki);
                $one['condition'] = "notin";
                $one['val'] = MDSArray::strToArray($vi,",");
                $i['where'][] = $one;
            }

            //条件等于
            if(strpos($ki,'whereEq_') !== false){
                $one['field'] = str_replace("whereEq_","",$ki);
                $one['condition'] = "eq";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //条件不等于
            if(strpos($ki,'whereNeq_') !== false){
                $one['field'] = str_replace("whereNeq_","",$ki);
                $one['condition'] = "neq";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //大于
            if(strpos($ki,'whereGt_') !== false){
                $one['field'] = str_replace("whereGt_","",$ki);
                $one['condition'] = "gt";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //大于等于
            if(strpos($ki,'whereEgt_') !== false){
                $one['field'] = str_replace("whereEgt_","",$ki);
                $one['condition'] = "egt";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //小于
            if(strpos($ki,'whereLt_') !== false){
                $one['field'] = str_replace("whereLt_","",$ki);
                $one['condition'] = "lt";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //小于等于
            if(strpos($ki,'whereElt_') !== false){
                $one['field'] = str_replace("whereElt_","",$ki);
                $one['condition'] = "elt";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //条件like
            if(strpos($ki,'whereLike_') !== false){
                $one['field'] = str_replace("whereLike_","",$ki);
                $one['condition'] = "like";
                $one['val'] = $vi;
                $i['where'][] = $one;
            }

            //范围值开始结束,默认结束whereEnd_
            if(strpos($ki,'whereBegin_') !== false){
                $one['field'] = str_replace("whereBegin_","",$ki);
                $one['condition'] = "between";
                $one['val'] = [];
                $one['val']['begin'] = $vi;
                $one['val']['end'] = isset($i['whereEnd_' . $one['field']]) ? $i['whereEnd_' . $one['field']] : 10000;
                $i['where'][] = $one;
            }

            //--orwhere----------------------------------------
            //在一堆数据中in,数据用逗号隔开
            if(strpos($ki,'whereOrIn_') !== false){
                $one['field'] = str_replace("whereOrIn_","",$ki);
                $one['condition'] = "orin";
                $one['val'] = MDSArray::strToArray($vi,",");
                $i['orWhere'][] = $one;
            }

            //不在某堆数据中
            if(strpos($ki,'whereOrNotIn_') !== false){
                $one['field'] = str_replace("whereOrNotIn_","",$ki);
                $one['condition'] = "ornotin";
                $one['val'] = MDSArray::strToArray($vi,",");
                $i['orWhere'][] = $one;
            }

            //条件等于
            if(strpos($ki,'whereOrEq_') !== false){
                $one['field'] = str_replace("whereOrEq_","",$ki);
                $one['condition'] = "oreq";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //条件不等于
            if(strpos($ki,'whereOrNeq_') !== false){
                $one['field'] = str_replace("whereOrNeq_","",$ki);
                $one['condition'] = "orneq";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //大于
            if(strpos($ki,'whereOrGt_') !== false){
                $one['field'] = str_replace("whereOrGt_","",$ki);
                $one['condition'] = "orgt";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //大于等于
            if(strpos($ki,'whereOrEgt_') !== false){
                $one['field'] = str_replace("whereOrEgt_","",$ki);
                $one['condition'] = "oregt";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //小于
            if(strpos($ki,'whereOrLt_') !== false){
                $one['field'] = str_replace("whereOrLt_","",$ki);
                $one['condition'] = "orlt";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //小于等于
            if(strpos($ki,'whereOrElt_') !== false){
                $one['field'] = str_replace("whereOrElt_","",$ki);
                $one['condition'] = "orelt";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //条件like
            if(strpos($ki,'whereOrLike_') !== false){
                $one['field'] = str_replace("whereOrLike_","",$ki);
                $one['condition'] = "orlike";
                $one['val'] = $vi;
                $i['orWhere'][] = $one;
            }

            //范围值开始结束,默认结束whereEnd_
            if(strpos($ki,'whereOrBegin_') !== false){
                $one['field'] = str_replace("whereOrBegin_","",$ki);
                $one['condition'] = "orbetween";
                $one['val'] = [];
                $one['val']['begin'] = $vi;
                $one['val']['end'] = isset($i['whereEnd_' . $one['field']]) ? $i['whereEnd_' . $one['field']] : 10000;
                $i['orWhere'][] = $one;
            }

            //--下面是插入和更新的数据梳理----------------------------------------
            if(strpos($ki,'dbData_') !== false){
                $field = str_replace("dbData_","",$ki);
                $i['dbData'][$field] = $vi;
            }

        }

        //d($i);
        return $i;
    }

    /**
     * 条件整理
     * 逐步完善
     * 一般情况
     */
    static public function splicingWhere($i,$query){
        //d($i);
        if(isset($i['where'])){
            foreach($i['where'] as $k => $v){
                if($v['condition'] == 'eq'){
                    $query->where($v['field'],$v['val']);
                }
                if($v['condition'] == 'neq'){
                    $query->where($v['field'],'<>',$v['val']);
                }
                if($v['condition'] == 'gt'){
                    $query->where($v['field'],'>',$v['val']);
                }
                if($v['condition'] == 'egt'){
                    $query->where($v['field'],'>=',$v['val']);
                }
                if($v['condition'] == 'lt'){
                    $query->where($v['field'],'<',$v['val']);
                }
                if($v['condition'] == 'elt'){
                    $query->where($v['field'],'<=',$v['val']);
                }
                if($v['condition'] == 'like'){
                    $query->where($v['field'], 'like', '%'.$v['val'].'%');
                }
                if($v['condition'] == 'between'){
                    $query->whereBetween($v['field'],[$v['val']['begin'],$v['val']['end']]);
                }
                if($v['condition'] == 'in'){
                    $query->whereIn($v['field'],$v['val']);
                }
                if($v['condition'] == 'notin'){
                    $query->whereNotIn($v['field'],$v['val']);
                }
            }
        }

        if(isset($i['orWhere'])){
            foreach($i['orWhere'] as $k => $v){
                if($v['condition'] == 'oreq'){
                    $query->orWhere($v['field'],$v['val']);
                }
                if($v['condition'] == 'orneq'){
                    $query->orWhere($v['field'],'<>',$v['val']);
                }
                if($v['condition'] == 'orgt'){
                    $query->orWhere($v['field'],'>',$v['val']);
                }
                if($v['condition'] == 'oregt'){
                    $query->orWhere($v['field'],'>=',$v['val']);
                }
                if($v['condition'] == 'orlt'){
                    $query->orWhere($v['field'],'<',$v['val']);
                }
                if($v['condition'] == 'orelt'){
                    $query->orWhere($v['field'],'<=',$v['val']);
                }
                if($v['condition'] == 'orlike'){
                    $query->orWhere($v['field'], 'like', '%'.$v['val'].'%');
                }
                if($v['condition'] == 'orbetween'){
                    $query->orWhereBetween($v['field'],[$v['val']['begin'],$v['val']['end']]);
                }
                if($v['condition'] == 'orin'){
                    $query->orWhereIn($v['field'],$v['val']);
                }
                if($v['condition'] == 'ornotin'){
                    $query->orWhereNotIn($v['field'],$v['val']);
                }
            }
        }

    }

    /**
     * 排序
     */
    static public function sort($i){
        //转换操作
        foreach($i as $ki => $vi){
            if(strpos($ki,'orderBy_') !== false){
                $one['field'] = str_replace("orderBy_","",$ki);
                $one['sort'] = $vi;
                $i['orderBy'][] = $one;
                unset($i[$ki]);
            }
        }
        return $i;
    }

}
